package PolishNotation;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * Author：zouran
 * Date：2023/4/30  19:47
 */
public class CalculateSuffix {
    //记录后缀表达式
    private final List<String> suffixList = new ArrayList<>();
    //记录操作数栈
    private final Stack<Double> operandStack = new Stack<>();

    //有参构造初始化
    public CalculateSuffix(List<String> list) {
        suffixList.addAll(list);
    }

    //判断是数字还是运算符,1为数字,2为运算符,0为未识别
    //默认识别 +，-，*，/，%，（），sqrt运算符
    public int judgeString(String s) {
        char[] chars = s.toCharArray();
        int i;
        //正数的情况
        for (i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (c < '0' || c > '9') {
                break;
            }
        }
        //负数的情况
        if (chars[0] == '-' && chars.length > 1) {
            for (i = 1; i < chars.length; i++) {
                char c = chars[i];
                if (c < '0' || c > '9') {
                    break;
                }
            }
        }
        if (i == chars.length)
            return 1;
        switch (s) {
            case "(", ")", "+", "-", "*", "/", "%", "sqrt" -> {
                return 2;
            }
            default -> {
                return 0;
            }
        }

    }

    //判断运算符类型
    public int judgeOperator(String operator) {
        switch (operator) {
            case "+", "-", "*", "/", "%", "pow" -> {
                return 2;
            }
            case "sqrt", "abs" -> {
                return 1;
            }
            default -> {
                return 0;
            }
        }
    }

    //计算弹幕运算符
    public Double oneOperator(Double a, String operator) {
        switch (operator) {
            case "sqrt" -> {
                return Math.sqrt(a);
            }
            case "abs" -> {
                return Math.abs(a);
            }
            default -> {
                return a;
            }
        }
    }

    //计算双目运算符
    public Double binaryOperator(Double a, Double b, String operator) {
        switch (operator) {
            case "+" -> {
                return a + b;
            }
            case "-" -> {
                return a - b;
            }
            case "*" -> {
                return a * b;
            }
            case "/" -> {
                return a / b;
            }
            case "%" -> {
                return (double) (Integer.parseInt(String.valueOf(Math.round(a))) % Integer.parseInt(String.valueOf(Math.round(b))));
            }
            default -> {
                return a;
            }
        }
    }

    //计算后缀表达式
    public Double calculateSuffix() {
        for (String s : suffixList) {
            if (judgeString(s) == 1)
                operandStack.push(Double.valueOf(s));
            else if (judgeString(s) == 2) {
                if (judgeOperator(s) == 1) {
                    Double top = operandStack.pop();
                    operandStack.push(oneOperator(top, s));
                } else if (judgeOperator(s) == 2) {
                    Double second = operandStack.pop();
                    Double first = operandStack.pop();
                    operandStack.push(binaryOperator(first, second, s));
                }
            }
        }
        return operandStack.pop();
    }
}
